package cool.webstudy.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cool.webstudy.admin.constant.CryptoConstant;
import cool.webstudy.admin.constant.TokenPayloadKeyConstant;
import cool.webstudy.admin.constant.enums.DelFlagEnum;
import cool.webstudy.admin.constant.enums.EnabledStatusFlagEnum;
import cool.webstudy.admin.constant.enums.rescode.UserResCodeEnum;
import cool.webstudy.admin.exception.BusinessException;
import cool.webstudy.admin.mapper.user.UserMapper;
import cool.webstudy.admin.model.dto.user.*;
import cool.webstudy.admin.model.po.user.UserPO;
import cool.webstudy.admin.model.vo.user.PaginationQueryUserInfoListVO;
import cool.webstudy.admin.model.vo.user.QueryCurrentUserVO;
import cool.webstudy.admin.model.vo.user.QueryUserDetailInfoVO;
import cool.webstudy.admin.model.vo.user.QueryUserRoughInfoVO;
import cool.webstudy.admin.service.UserService;
import cool.webstudy.admin.utils.JwtUtil;
import cool.webstudy.admin.utils.UserDetailUtil;
import cool.webstudy.admin.utils.crypto.AESUtil;
import cool.webstudy.common.utils.UUIDUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author think
 * @date 2024/7/14 22:08
 * @description: 用户管理接口实现类
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserMapper userMapper;

    /**
     * @param unCode 用户业务主键
     * @return UserPO 用户信息实体
     * @description: 判断用户是否存在，如果存在，则返回该用户的信息实体
     */
    @Override
    public UserPO isExist(String unCode) {
        LambdaQueryWrapper<UserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPO::getUnCode, unCode)
                .eq(UserPO::getStatusFlag, EnabledStatusFlagEnum.ENABLED.getFlag());
        UserPO user = userMapper.selectOne(queryWrapper);
        if (Objects.nonNull(user)) {
            return user;
        }
        return null;
    }

    /**
     * @param dto 登录信息实体类
     * @return String token 令牌
     * @description: 用户登录方法
     */
    @Override
    public String login(UserLoginDTO dto) {
        LambdaQueryWrapper<UserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPO::getAccount, dto.getAccount())
                .eq(UserPO::getStatusFlag, EnabledStatusFlagEnum.ENABLED.getFlag());
        UserPO user = userMapper.selectOne(queryWrapper);
        if (Objects.isNull(user)) {
            throw new BusinessException(UserResCodeEnum.RC_USER_NOT_EXIST);
        } else {
            boolean match = passwordEncoder.matches(dto.getPassword(), user.getPassword());
            if (!match) {
                throw new BusinessException(UserResCodeEnum.RC_ERROR_PASSWORD);
            }
            // 生成token并返回
            JwtUtil jwtUtil = new JwtUtil();
            Map<String, Object> payload = new HashMap<>();
            payload.put(TokenPayloadKeyConstant.USERINFO, AESUtil.encode(user.getUnCode(), CryptoConstant.AES_KEY));
            return jwtUtil.encode(user.getUsername(), 500 * 60 * 1000, payload);
        }
    }

    /**
     * @return QueryCurrentUserVO 查询当前用户信息接口响应信息模型
     * @description: 查询当前用户信息
     */
    @Override
    public QueryCurrentUserVO queryCurrentUser() {
        UserDetailInfoDTO userDetailInfo = UserDetailUtil.getUserDetailInfo();
        LambdaQueryWrapper<UserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPO::getUnCode, userDetailInfo.getUnCode())
                .eq(UserPO::getStatusFlag, EnabledStatusFlagEnum.ENABLED.getFlag());
        UserPO user = userMapper.selectOne(queryWrapper);
        if (Objects.isNull(user)) {
            throw new BusinessException(UserResCodeEnum.RC_USER_NOT_EXIST);
        }
        QueryCurrentUserVO queryCurrentUserVO = new QueryCurrentUserVO();
        queryCurrentUserVO.setUsername(user.getUsername());
        return queryCurrentUserVO;
    }

    /**
     * @param unCode 业务主键
     * @return QueryUserDetailInfoVO 查询用户详细信息接口响应参数模型
     * @description: 查询用户详细信息
     */
    @Override
    public QueryUserDetailInfoVO queryUserDetailInfo(String unCode) {
        LambdaQueryWrapper<UserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPO::getUnCode, unCode)
                .select(UserPO::getUnCode, UserPO::getAccount, UserPO::getUsername, UserPO::getAccount, UserPO::getRole, UserPO::getStatusFlag);
        UserPO user = userMapper.selectOne(queryWrapper);
        if (Objects.isNull(user)) {
            throw new BusinessException(UserResCodeEnum.RC_USER_NOT_EXIST);
        }
        QueryUserDetailInfoVO queryUserDetailInfoVO = new QueryUserDetailInfoVO();
        queryUserDetailInfoVO.setUnCode(user.getUnCode());
        queryUserDetailInfoVO.setUsername(user.getUsername());
        queryUserDetailInfoVO.setAccount(user.getAccount());
        queryUserDetailInfoVO.setRole(user.getRole());
        queryUserDetailInfoVO.setStatusFlag(user.getStatusFlag());
        return queryUserDetailInfoVO;
    }

    /**
     * @param dto 创建用户接口请求参数模型
     * @return Boolean 是否成功标识
     * @description: 创建用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createUser(CreateUserDTO dto) {
        UserDetailInfoDTO userDetailInfo = UserDetailUtil.getUserDetailInfo();
        UserPO user = new UserPO();
        user.setAccount(dto.getAccount());
        user.setUsername(dto.getUsername());
        user.setPassword(passwordEncoder.encode(dto.getPassword()));
        user.setRole(dto.getRole());
        user.setStatusFlag(EnabledStatusFlagEnum.ENABLED);
        user.setUnCode(UUIDUtil.getUUID());
        user.setCreateBy(userDetailInfo.getAccount());
        user.setCreateTime(new Date());
        user.setUpdateBy(userDetailInfo.getAccount());
        user.setUpdateTime(new Date());
        user.setDelFlag(DelFlagEnum.NOT_DEL_FLAG.getFlag());
        try {
            userMapper.insert(user);
        } catch (Exception e) {
            throw new BusinessException(UserResCodeEnum.RC_ERROR_CREATE);
        }
        return true;
    }

    /**
     * @param dto 更新用户接口请求参数模型
     * @return Boolean 是否成功标识
     * @description: 更新用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateUser(UpdateUserDTO dto) {
        UserDetailInfoDTO userDetailInfo = UserDetailUtil.getUserDetailInfo();
        LambdaUpdateWrapper<UserPO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(UserPO::getUnCode, dto.getUnCode())
                .set(StringUtils.isNotBlank(dto.getUsername()), UserPO::getUsername, dto.getUsername())
                .set(StringUtils.isNotBlank(dto.getPassword()), UserPO::getPassword, passwordEncoder.encode(dto.getPassword()))
                .set(StringUtils.isNotBlank(dto.getRole()), UserPO::getRole, dto.getRole())
                .set(StringUtils.isNotBlank(dto.getStatusFlag()), UserPO::getStatusFlag, dto.getStatusFlag())
                .set(UserPO::getUpdateBy, userDetailInfo.getAccount())
                .set(UserPO::getUpdateTime, new Date());
        try {
            userMapper.update(null, updateWrapper);
        } catch (Exception e) {
            throw new BusinessException(UserResCodeEnum.RC_ERROR_UPDATE);
        }
        return true;
    }

    /**
     * @param unCodeList 业务主键列表
     * @return Boolean 是否成功标识
     * @description: 批量删除用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteUser(List<String> unCodeList) {
        if (unCodeList == null || unCodeList.isEmpty()) {
            throw new BusinessException(UserResCodeEnum.RC_ERROR_BATCH_DELETE);
        }
        UserDetailInfoDTO userDetailInfo = UserDetailUtil.getUserDetailInfo();
        LambdaUpdateWrapper<UserPO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(UserPO::getUnCode, unCodeList)
                .set(UserPO::getUpdateBy, userDetailInfo.getAccount())
                .set(UserPO::getUpdateTime, new Date())
                .set(UserPO::getDelFlag, DelFlagEnum.DEL_FLAG.getFlag());
        try {
            userMapper.update(null, updateWrapper);
        } catch (Exception e) {
            throw new BusinessException(UserResCodeEnum.RC_ERROR_BATCH_DELETE);
        }
        return true;
    }

    /**
     * @param dto 分页获取信息列表接口请求参数基础模型
     * @return Page<PaginationQueryUserInfoListVO> 分页获取用户信息列表接口响应模型
     * @description: 分页获取用户信息列表
     */
    @Override
    public Page<PaginationQueryUserInfoListVO> paginationQueryUserInfoList(PaginationQueryUserInfoListDTO dto) {
        Page<PaginationQueryUserInfoListVO> paginationQueryUserInfoListVOPage = new Page<>();
        Page<UserPO> page = new Page<>(dto.getCurrent(), dto.getPageSize());
        LambdaQueryWrapper<UserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(dto.getContext()), UserPO::getAccount, dto.getContext())
                .or().like(StringUtils.isNotBlank(dto.getContext()), UserPO::getUsername, dto.getContext())
                .eq(StringUtils.isNotBlank(dto.getRole()), UserPO::getRole, dto.getRole())
                .eq(StringUtils.isNotBlank(dto.getStatusFlag()), UserPO::getStatusFlag, dto.getStatusFlag());
        Page<UserPO> userPOPage = userMapper.selectPage(page, queryWrapper);
        if (Objects.isNull(userPOPage)) {
            return paginationQueryUserInfoListVOPage;
        }
        List<PaginationQueryUserInfoListVO> paginationQueryUserInfoListVOList = new ArrayList<>();
        userPOPage.getRecords().forEach(userPO -> {
            PaginationQueryUserInfoListVO paginationQueryUserInfoListVO = new PaginationQueryUserInfoListVO();
            paginationQueryUserInfoListVO.setUnCode(userPO.getUnCode());
            paginationQueryUserInfoListVO.setAccount(userPO.getAccount());
            paginationQueryUserInfoListVO.setUsername(userPO.getUsername());
            paginationQueryUserInfoListVO.setRole(userPO.getRole());
            paginationQueryUserInfoListVO.setStatusFlag(userPO.getStatusFlag());
            paginationQueryUserInfoListVO.setCreateBy(userPO.getCreateBy());
            paginationQueryUserInfoListVO.setCreateTime(userPO.getCreateTime());
            paginationQueryUserInfoListVO.setUpdateBy(userPO.getUpdateBy());
            paginationQueryUserInfoListVO.setUpdateTime(userPO.getUpdateTime());
            paginationQueryUserInfoListVOList.add(paginationQueryUserInfoListVO);
        });
        paginationQueryUserInfoListVOPage.setRecords(paginationQueryUserInfoListVOList);
        paginationQueryUserInfoListVOPage.setCurrent(userPOPage.getCurrent());
        paginationQueryUserInfoListVOPage.setPages(userPOPage.getPages());
        paginationQueryUserInfoListVOPage.setSize(userPOPage.getSize());
        paginationQueryUserInfoListVOPage.setTotal(userPOPage.getTotal());
        return paginationQueryUserInfoListVOPage;
    }

    /**
     * @param context 模糊搜索关键词
     * @return List<QueryUserRoughInfoVO> 获取用户粗略信息接口响应信息模型
     * @description: 根据用户名或者账号获取启用用户粗略信息列表
     */
    @Override
    public List<QueryUserRoughInfoVO> queryEnabledUserRoughInfoByUserNameOrAccount(String context) {
        List<QueryUserRoughInfoVO> queryUserRoughInfoVOList = new ArrayList<>();
        LambdaQueryWrapper<UserPO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(context), UserPO::getAccount, context)
                .or().like(StringUtils.isNotBlank(context), UserPO::getUsername, context)
                .eq(UserPO::getStatusFlag, EnabledStatusFlagEnum.ENABLED)
                .select(UserPO::getUnCode,UserPO::getUsername);
        List<UserPO> userPOList = userMapper.selectList(queryWrapper);
        if (Objects.isNull(userPOList)) {
            return queryUserRoughInfoVOList;
        }
        userPOList.forEach(userPO -> {
            QueryUserRoughInfoVO queryUserRoughInfoVO = new QueryUserRoughInfoVO();
            queryUserRoughInfoVO.setUnCode(userPO.getUnCode());
            queryUserRoughInfoVO.setUsername(userPO.getUsername());
            queryUserRoughInfoVOList.add(queryUserRoughInfoVO);
        });
        return queryUserRoughInfoVOList;
    }
}
